package com.hx.mylombok.processor;

import com.hx.mylombok.factory.FileGenerateFactory;
import com.hx.mylombok.task.FileTask;
import com.hx.mylombok.task.TaskEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ExecutableType;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author guoxiaolin
 * @version v2.0
 * @description
 * @since 2019/3/27 15:10
 */
@SupportedAnnotationTypes(value = {"com.hx.mylombok.annotation.ProxyController"})
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
public class ProxyControllerProcessor extends AbstractProcessor {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public ProxyControllerProcessor() {
        logger.info("==== ProxyControllerProcessor 构造函数 ===");
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        logger.info("===============  enter process   ================");
        for (TypeElement typeElement : annotations) {
            Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(typeElement);
            for (Element el : annotatedElements) {
                logger.info("处理类 : " + el.toString());
                String className = el.toString();
                Map<String, List<Element>> annotatedMethods = el.getEnclosedElements().stream().collect(Collectors.groupingBy(
                        element -> element.getKind().toString()));
                if (annotatedMethods.size() == 0){
                    logger.info("annotatedMethods is null ");
                    try {
                        writeBuilderFile(className, new HashMap<>());
                    } catch (IOException e) {
                        logger.error(e.getMessage());
                    }
                }else{
                    logger.info("annotatedMethods is  " + annotatedMethods);
                    for (String str1 : annotatedMethods.keySet()) {
                        List<Element> setters = annotatedMethods.get(str1);
                        if (setters.get(0).getKind().isClass()){
                        }else if (setters.get(0).getKind().isField()){
                        }else if (setters.get(0).getKind().isInterface()){
                        }else{
                            Map<String, String> setterMap = setters.stream().collect(Collectors.toMap(
                                    setter -> setter.getSimpleName().toString(),
                                    setter -> ((ExecutableType) setter.asType()).getReturnType() + "," + ((ExecutableType) setter.asType()).getParameterTypes().toString()
                            ));
                            try {
                                writeBuilderFile(className, setterMap);
                            } catch (IOException e) {
                                logger.error(e.getMessage());
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    private void writeBuilderFile(String className, Map<String, String> setterMap) throws IOException {

        FileGenerateFactory fileGenerateFactory = new FileGenerateFactory();

        FileTask proxyController = fileGenerateFactory.getTask(TaskEnum.PROXYCONTROLLER,className);
        proxyController.generateFile(setterMap, processingEnv);

        FileTask controller = fileGenerateFactory.getTask(TaskEnum.CONTROLLER,className);
        controller.generateFile(setterMap, processingEnv);

        FileTask feignProxyFallback = fileGenerateFactory.getTask(TaskEnum.FEIGNPROXYFALLBACK,className);
        feignProxyFallback.generateFile(setterMap, processingEnv);

        FileTask proxy = fileGenerateFactory.getTask(TaskEnum.PROXY,className);
        proxy.generateFile(setterMap, processingEnv);

        FileTask feignProxy = fileGenerateFactory.getTask(TaskEnum.IFEIGNPROXY,className);
        feignProxy.generateFile(setterMap, processingEnv);

        FileTask repository = fileGenerateFactory.getTask(TaskEnum.REPOSITORY,className);
        repository.generateFile(setterMap, processingEnv);

        FileTask abstractService = fileGenerateFactory.getTask(TaskEnum.ABSTRACTSERVICE,className);
        abstractService.generateFile(setterMap, processingEnv);

        FileTask implService = fileGenerateFactory.getTask(TaskEnum.IMPLSERVICE,className);
        implService.generateFile(setterMap, processingEnv);

    }
}